# Librerias
require(tidyverse)
Loading required package: tidyverse
Registered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
── Attaching packages ───────────────────────────────────────────────────────────── tidyverse 1.3.1 ──
✓ ggplot2 3.3.5 ✓ purrr 0.3.4
✓ tibble 3.1.4 ✓ dplyr 1.0.7
✓ tidyr 1.1.4 ✓ stringr 1.4.0
✓ readr 2.0.1 ✓ forcats 0.5.1
── Conflicts ──────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag() masks stats::lag()
require(geosphere)
Loading required package: geosphere
require(rvest) # Cargamos el paquete
Loading required package: rvest
Attaching package: ‘rvest’
The following object is masked from ‘package:readr’:
guess_encoding
# Llamamos a los DataSets
datos_2014 = read.csv('../TP_LaboDeDatos/Data/aterrizajes-y-despegues-registrados-por-eana-2014.csv', encoding = 'latin1', sep = ';')
datos_2015 = read.csv('../TP_LaboDeDatos/Data/aterrizajes-y-despegues-registrados-por-eana-2015.csv', encoding = 'latin1', sep = ';')
datos_2016 = read.csv('../TP_LaboDeDatos/Data/aterrizajes-y-despegues-registrados-por-eana-2016.csv', encoding = 'latin1', sep = ';')
datos_2017 = read.csv('../TP_LaboDeDatos/Data/aterrizajes-y-despegues-registrados-por-eana-2017.csv', encoding = 'latin1', sep = ';')
datos_2018 = read.csv('../TP_LaboDeDatos/Data/aterrizajes-y-despegues-registrados-por-eana-2018.csv', encoding = 'latin1', sep = ';')
datos_2019 = read.csv('../TP_LaboDeDatos/Data/aterrizajes-y-despegues-registrados-por-eana-2019.csv', encoding = 'latin1', sep = ';')
datos_2020 = read.csv('../TP_LaboDeDatos/Data/aterrizajes-y-despegues-registrados-por-eana-2020.csv', encoding = 'latin1', sep = ';')
# Concateno todos los datos
datos = rbind(datos_2014,datos_2015,datos_2016,datos_2017,datos_2018,datos_2019,datos_2020)
datos2= read.csv('../TP_LaboDeDatos/Data/202109-informe-ministerio.csv', encoding = 'latin1', sep = ';')
# Utilizamos la tabla que se encuentra en 'https://en.wikipedia.org/wiki/List_of_airports_in_Argentina'
# para acceder a las variables de ciudad, provincia y coordenadas de cada aeropuerto
aeropuertos_wiki = read_html('https://en.wikipedia.org/wiki/List_of_airports_in_Argentina')
elemento_tabla = html_element(aeropuertos_wiki,'.wikitable')
aeropuertos = html_table(elemento_tabla)
# Variables utiles
N = dim(datos)[1]
cant_aeropuertos = dim(aeropuertos)[1]
# Corrijo la columna de coordenadas
separar = strsplit((aeropuertos$Coordinates), '/') # Divide a los strings en los lugares donde haya '/'
coordenadas = sapply(separar, function(x) x[3]) # Me quedo solo con el 3er tipo de coordenada
coordenadas = gsub('[^0-9,.,-]','', coordenadas) # Elimino los caracteres que no quiero utilizar
aeropuertos = aeropuertos %>%
mutate(lat = as.numeric(substr(coordenadas, 1, 9)), long = as.numeric(substr(coordenadas, 10, 18))) # Separo a mano latitud y longitud (revizar si esta todo en orden)
aeropuertos = filter(aeropuertos, nchar(ICAO)>1)
aeropuertos = aeropuertos[order(aeropuertos$ICAO),]
unique(datos2$Origen...Destino)
[1] "TUC" "JUJ" "EZE" "ROS" "CRR" "SDE" "RES" "CRD" "ORA" "SFN" "SLA" "VMR" "MCS" "GNR" "FMA" "PEH"
[17] "CUT"
Una pregunta que nos pareció interesante es ver qué pares de aeropuertos se comunican más. Para eso hicimos un mapa de calor. En el mismo se puede notar que no todos los vuelos tienen registrado tanto su despegue como aterrizaje, y de hecho hay aeropuertos donde no se registran los vuelos (por eso solo aparecen como el otro aeropuerto en los registros)
library(ggplot2)
aersA = unique(datos2$Aeropuerto)
aersB = unique(datos2$Origen...Destino)
mat = matrix(nrow = length(aersA), ncol = length(aersB))
row.names(mat) = aersA
colnames(mat) = aersB
for(i in 1:length(aersA)){
for(j in 1:length(aersB)){
mat[i,j] = sum((datos2$Aeropuerto==aersA[i]) & (datos2$Origen...Destino==aersB[j]))
}
}
#heatmap(mat,Colv = NA, Rowv = NA, scale="column")
library(heatmaply)
help("heatmaply")
heatmaply(mat,cellnote=mat, Rowv = NA, Colv = NA, col_dend_up=TRUE, ylab="Aeropuerto", xlab="Origen/Destino")%>%
layout(xaxis = list(side = "top"))
Notar que los vuelos que empiezan y terminan en el mismo aeropuerto, que son casi la mitad, es muy factible que sean vuelos de entrenamiento.
En aersC podemos ver los aeropuertos que no registran los eventos que ocurren en ellos. Al menos si consideramos solo los vuelos nacionales.
aersC = NULL
for(x in aersB){
if(sum(aersA==x)==0)
{
if(is.null(aersC)) aersC = c(x)
else aersC = c(aersC,x)
}
}
print(aersC)
[1] "RES" "CRD" "ORA" "SFN" "SLA" "VMR" "MCS" "GNR" "FMA" "PEH" "CUT"
#Por ahora esta parte no sirve pero está bueno tenerla
# Agregando Ciudades
datos$ciudad_origen = rep(NA, length(N))
datos$ciudad_destino = rep(NA, length(N))
datos$provincia_origen = rep(NA, length(N))
datos$provincia_destino = rep(NA, length(N))
datos$lat_origen = rep(NA, length(N))
datos$long_origen = rep(NA, length(N))
datos$lat_destino = rep(NA, length(N))
datos$long_destino = rep(NA, length(N))
# datos %>% mutate(ciudad_origen = ) # Aca queria hacer exactamente lo de arriba pero usando dplyr
# El algoritmo de abajo ndar anda, tarda un monton. Hay que agregar el resto de las variables
for(i in 1:length(aeropuertos$ICAO)){
inds = datos$Origen.OACI==aeropuertos$ICAO[i]
datos[inds,c('ciudad_origen','provincia_origen','lat_origen','long_origen')] = aeropuertos[i,c("City served","Province","lat","long")]
inds = datos$Origen.OACI==aeropuertos$ICAO[i]
datos[inds,c('ciudad_destino','provincia_destino','lat_destino','long_destino')] = aeropuertos[i,c("City served","Province","lat","long")]
}
datos = drop_na(datos)
datos$distancia = distHaversine(datos[,c("long_origen","lat_origen")],datos[,c("long_destino","lat_destino")])
LS0tCnRpdGxlOiAiVHJhYmFqbyBQcmFjdGljbyAtIExhYm9yYXRvcmlvIGRlIERhdG9zIgphdXRob3I6ICJNb3JhbGVzIEpvYXF1aW4sIExhc29yc2EgTGF1dGFybyB5IFBhbGF6em8gVG9tYXMiCmRhdGU6ICIxNC8xMC8yMDIxIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiB5ZXMKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IGx1bWVuCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKc3VidGl0bGU6ICJMYWJvcmF0b3JpbyBkZSBEYXRvcyIKLS0tCgpgYGB7cn0KIyBMaWJyZXJpYXMKcmVxdWlyZSh0aWR5dmVyc2UpCnJlcXVpcmUoZ2Vvc3BoZXJlKQpyZXF1aXJlKHJ2ZXN0KSAjIENhcmdhbW9zIGVsIHBhcXVldGUKYGBgCgoKYGBge3J9CiMgTGxhbWFtb3MgYSBsb3MgRGF0YVNldHMKCmRhdG9zXzIwMTQgPSByZWFkLmNzdignLi4vVFBfTGFib0RlRGF0b3MvRGF0YS9hdGVycml6YWplcy15LWRlc3BlZ3Vlcy1yZWdpc3RyYWRvcy1wb3ItZWFuYS0yMDE0LmNzdicsIGVuY29kaW5nID0gJ2xhdGluMScsIHNlcCA9ICc7JykKZGF0b3NfMjAxNSA9IHJlYWQuY3N2KCcuLi9UUF9MYWJvRGVEYXRvcy9EYXRhL2F0ZXJyaXphamVzLXktZGVzcGVndWVzLXJlZ2lzdHJhZG9zLXBvci1lYW5hLTIwMTUuY3N2JywgZW5jb2RpbmcgPSAnbGF0aW4xJywgc2VwID0gJzsnKQpkYXRvc18yMDE2ID0gcmVhZC5jc3YoJy4uL1RQX0xhYm9EZURhdG9zL0RhdGEvYXRlcnJpemFqZXMteS1kZXNwZWd1ZXMtcmVnaXN0cmFkb3MtcG9yLWVhbmEtMjAxNi5jc3YnLCBlbmNvZGluZyA9ICdsYXRpbjEnLCBzZXAgPSAnOycpCmRhdG9zXzIwMTcgPSByZWFkLmNzdignLi4vVFBfTGFib0RlRGF0b3MvRGF0YS9hdGVycml6YWplcy15LWRlc3BlZ3Vlcy1yZWdpc3RyYWRvcy1wb3ItZWFuYS0yMDE3LmNzdicsIGVuY29kaW5nID0gJ2xhdGluMScsIHNlcCA9ICc7JykKZGF0b3NfMjAxOCA9IHJlYWQuY3N2KCcuLi9UUF9MYWJvRGVEYXRvcy9EYXRhL2F0ZXJyaXphamVzLXktZGVzcGVndWVzLXJlZ2lzdHJhZG9zLXBvci1lYW5hLTIwMTguY3N2JywgZW5jb2RpbmcgPSAnbGF0aW4xJywgc2VwID0gJzsnKQpkYXRvc18yMDE5ID0gcmVhZC5jc3YoJy4uL1RQX0xhYm9EZURhdG9zL0RhdGEvYXRlcnJpemFqZXMteS1kZXNwZWd1ZXMtcmVnaXN0cmFkb3MtcG9yLWVhbmEtMjAxOS5jc3YnLCBlbmNvZGluZyA9ICdsYXRpbjEnLCBzZXAgPSAnOycpCmRhdG9zXzIwMjAgPSByZWFkLmNzdignLi4vVFBfTGFib0RlRGF0b3MvRGF0YS9hdGVycml6YWplcy15LWRlc3BlZ3Vlcy1yZWdpc3RyYWRvcy1wb3ItZWFuYS0yMDIwLmNzdicsIGVuY29kaW5nID0gJ2xhdGluMScsIHNlcCA9ICc7JykKCiMgQ29uY2F0ZW5vIHRvZG9zIGxvcyBkYXRvcwpkYXRvcyA9IHJiaW5kKGRhdG9zXzIwMTQsZGF0b3NfMjAxNSxkYXRvc18yMDE2LGRhdG9zXzIwMTcsZGF0b3NfMjAxOCxkYXRvc18yMDE5LGRhdG9zXzIwMjApCmRhdG9zMj0gcmVhZC5jc3YoJy4uL1RQX0xhYm9EZURhdG9zL0RhdGEvMjAyMTA5LWluZm9ybWUtbWluaXN0ZXJpby5jc3YnLCBlbmNvZGluZyA9ICdsYXRpbjEnLCBzZXAgPSAnOycpCmBgYAoKYGBge3J9CiMgVXRpbGl6YW1vcyBsYSB0YWJsYSBxdWUgc2UgZW5jdWVudHJhIGVuICdodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MaXN0X29mX2FpcnBvcnRzX2luX0FyZ2VudGluYScKIyBwYXJhIGFjY2VkZXIgYSBsYXMgdmFyaWFibGVzIGRlIGNpdWRhZCwgcHJvdmluY2lhIHkgY29vcmRlbmFkYXMgZGUgY2FkYSBhZXJvcHVlcnRvIAoKYWVyb3B1ZXJ0b3Nfd2lraSA9IHJlYWRfaHRtbCgnaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGlzdF9vZl9haXJwb3J0c19pbl9BcmdlbnRpbmEnKQplbGVtZW50b190YWJsYSAgID0gaHRtbF9lbGVtZW50KGFlcm9wdWVydG9zX3dpa2ksJy53aWtpdGFibGUnKQphZXJvcHVlcnRvcyAgICAgID0gaHRtbF90YWJsZShlbGVtZW50b190YWJsYSkKCgojIFZhcmlhYmxlcyB1dGlsZXMKTiA9IGRpbShkYXRvcylbMV0KY2FudF9hZXJvcHVlcnRvcyA9IGRpbShhZXJvcHVlcnRvcylbMV0KCmBgYAoKYGBge3J9CiMgQ29ycmlqbyBsYSBjb2x1bW5hIGRlIGNvb3JkZW5hZGFzIAoKc2VwYXJhciAgICAgPSBzdHJzcGxpdCgoYWVyb3B1ZXJ0b3MkQ29vcmRpbmF0ZXMpLCAnLycpICMgRGl2aWRlIGEgbG9zIHN0cmluZ3MgZW4gbG9zIGx1Z2FyZXMgZG9uZGUgaGF5YSAnLycgCmNvb3JkZW5hZGFzID0gc2FwcGx5KHNlcGFyYXIsIGZ1bmN0aW9uKHgpIHhbM10pICAgICAgICAjIE1lIHF1ZWRvIHNvbG8gY29uIGVsIDNlciB0aXBvIGRlIGNvb3JkZW5hZGEKY29vcmRlbmFkYXMgPSBnc3ViKCdbXjAtOSwuLC1dJywnJywgY29vcmRlbmFkYXMpICAgICAgICAgICAjIEVsaW1pbm8gbG9zIGNhcmFjdGVyZXMgcXVlIG5vIHF1aWVybyB1dGlsaXphcgoKYWVyb3B1ZXJ0b3MgPSBhZXJvcHVlcnRvcyAlPiUgCiAgbXV0YXRlKGxhdCA9IGFzLm51bWVyaWMoc3Vic3RyKGNvb3JkZW5hZGFzLCAxLCA5KSksIGxvbmcgPSBhcy5udW1lcmljKHN1YnN0cihjb29yZGVuYWRhcywgMTAsIDE4KSkpICMgU2VwYXJvIGEgbWFubyBsYXRpdHVkIHkgbG9uZ2l0dWQgKHJldml6YXIgc2kgZXN0YSB0b2RvIGVuIG9yZGVuKQoKYWVyb3B1ZXJ0b3MgPSBmaWx0ZXIoYWVyb3B1ZXJ0b3MsIG5jaGFyKElDQU8pPjEpCmFlcm9wdWVydG9zID0gYWVyb3B1ZXJ0b3Nbb3JkZXIoYWVyb3B1ZXJ0b3MkSUNBTyksXQpgYGAKCmBgYHtyfQojUG9yIGFob3JhIGVzdGEgcGFydGUgbm8gc2lydmUgcGVybyBlc3TDoSBidWVubyB0ZW5lcmxhCiMgQWdyZWdhbmRvIENpdWRhZGVzCk4yID0gbGVuZ3RoKGRhdG9zMiRIb3JhLlVUQykKZGF0b3MyJGNpdWRhZF9vcmlnZW4gICAgID0gcmVwKE5BLCBsZW5ndGgoTjIpKQpkYXRvczIkY2l1ZGFkX2Rlc3Rpbm8gICAgPSByZXAoTkEsIGxlbmd0aChOMikpCmRhdG9zMiRwcm92aW5jaWFfb3JpZ2VuICA9IHJlcChOQSwgbGVuZ3RoKE4yKSkKZGF0b3MyJHByb3ZpbmNpYV9kZXN0aW5vID0gcmVwKE5BLCBsZW5ndGgoTjIpKQpkYXRvczIkbGF0X29yaWdlbiAgICAgICAgPSByZXAoTkEsIGxlbmd0aChOMikpIApkYXRvczIkbG9uZ19vcmlnZW4gICAgICAgPSByZXAoTkEsIGxlbmd0aChOMikpIApkYXRvczIkbGF0X2Rlc3Rpbm8gICAgICAgPSByZXAoTkEsIGxlbmd0aChOMikpIApkYXRvczIkbG9uZ19kZXN0aW5vICAgICAgPSByZXAoTkEsIGxlbmd0aChOMikpIAojIGRhdG9zICU+JSBtdXRhdGUoY2l1ZGFkX29yaWdlbiA9ICkgIyBBY2EgcXVlcmlhIGhhY2VyIGV4YWN0YW1lbnRlIGxvIGRlIGFycmliYSBwZXJvIHVzYW5kbyBkcGx5cgoKCgojIEVsIGFsZ29yaXRtbyBkZSBhYmFqbyBuZGFyIGFuZGEsIHRhcmRhIHVuIG1vbnRvbi4gSGF5IHF1ZSBhZ3JlZ2FyIGVsIHJlc3RvIGRlIGxhcyB2YXJpYWJsZXMKCmZvcihpIGluIDE6bGVuZ3RoKGFlcm9wdWVydG9zJElDQU8pKXsKICBpbmRzID0gZGF0b3MyJEFlcm9wdWVydG89PWFlcm9wdWVydG9zJElBVEFbaV0KICBkYXRvczJbaW5kcyxjKCdjaXVkYWRfb3JpZ2VuJywncHJvdmluY2lhX29yaWdlbicsJ2xhdF9vcmlnZW4nLCdsb25nX29yaWdlbicpXSA9IGFlcm9wdWVydG9zW2ksYygiQ2l0ecKgc2VydmVkIiwiUHJvdmluY2UiLCJsYXQiLCJsb25nIildCiAgCiAgaW5kcyA9IGRhdG9zMiRPcmlnZW4uLi5EZXN0aW5vPT1hZXJvcHVlcnRvcyRJQVRBW2ldCiAgZGF0b3MyW2luZHMsYygnY2l1ZGFkX2Rlc3Rpbm8nLCdwcm92aW5jaWFfZGVzdGlubycsJ2xhdF9kZXN0aW5vJywnbG9uZ19kZXN0aW5vJyldID0gYWVyb3B1ZXJ0b3NbaSxjKCJDaXR5wqBzZXJ2ZWQiLCJQcm92aW5jZSIsImxhdCIsImxvbmciKV0KICAKICAKfQpkYXRvczIgPSBkcm9wX25hKGRhdG9zMikKZGF0b3MyJGRpc3RhbmNpYSA9IGRpc3RIYXZlcnNpbmUoZGF0b3MyWyxjKCJsb25nX29yaWdlbiIsImxhdF9vcmlnZW4iKV0sZGF0b3MyWyxjKCJsb25nX2Rlc3Rpbm8iLCJsYXRfZGVzdGlubyIpXSkKdW5pcXVlKGRhdG9zMiRPcmlnZW4uLi5EZXN0aW5vKQpgYGAKVW5hIHByZWd1bnRhIHF1ZSBub3MgcGFyZWNpw7MgaW50ZXJlc2FudGUgZXMgdmVyIHF1w6kgcGFyZXMgZGUgYWVyb3B1ZXJ0b3Mgc2UgY29tdW5pY2FuIG3DoXMuIFBhcmEgZXNvIGhpY2ltb3MgdW4gbWFwYSBkZSBjYWxvci4gRW4gZWwgbWlzbW8gc2UgcHVlZGUgbm90YXIgcXVlIG5vIHRvZG9zIGxvcyB2dWVsb3MgdGllbmVuIHJlZ2lzdHJhZG8gdGFudG8gc3UgZGVzcGVndWUgY29tbyBhdGVycml6YWplLCB5IGRlIGhlY2hvIGhheSBhZXJvcHVlcnRvcyBkb25kZSBubyBzZSByZWdpc3RyYW4gbG9zIHZ1ZWxvcyAocG9yIGVzbyBzb2xvIGFwYXJlY2VuIGNvbW8gZWwgb3RybyBhZXJvcHVlcnRvIGVuIGxvcyByZWdpc3Ryb3MpCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmFlcnNBID0gdW5pcXVlKGRhdG9zMiRBZXJvcHVlcnRvKQphZXJzQiA9IHVuaXF1ZShkYXRvczIkT3JpZ2VuLi4uRGVzdGlubykKbWF0ID0gbWF0cml4KG5yb3cgPSBsZW5ndGgoYWVyc0EpLCBuY29sID0gbGVuZ3RoKGFlcnNCKSkKcm93Lm5hbWVzKG1hdCkgPSBhZXJzQQpjb2xuYW1lcyhtYXQpID0gYWVyc0IKZm9yKGkgaW4gMTpsZW5ndGgoYWVyc0EpKXsKICBmb3IoaiBpbiAxOmxlbmd0aChhZXJzQikpewogICAgbWF0W2ksal0gID0gIHN1bSgoZGF0b3MyJEFlcm9wdWVydG89PWFlcnNBW2ldKSAmIChkYXRvczIkT3JpZ2VuLi4uRGVzdGlubz09YWVyc0Jbal0pKQogIH0KfQojaGVhdG1hcChtYXQsQ29sdiA9IE5BLCBSb3d2ID0gTkEsIHNjYWxlPSJjb2x1bW4iKQpsaWJyYXJ5KGhlYXRtYXBseSkKaGVscCgiaGVhdG1hcGx5IikKaGVhdG1hcGx5KG1hdCxjZWxsbm90ZT1tYXQsIFJvd3YgPSBOQSwgQ29sdiA9IE5BLCBjb2xfZGVuZF91cD1UUlVFLCB5bGFiPSJBZXJvcHVlcnRvIiwgeGxhYj0iT3JpZ2VuL0Rlc3Rpbm8iKSU+JSAKICBsYXlvdXQoeGF4aXMgPSBsaXN0KHNpZGUgPSAidG9wIikpCmBgYApOb3RhciBxdWUgbG9zIHZ1ZWxvcyBxdWUgZW1waWV6YW4geSB0ZXJtaW5hbiBlbiBlbCBtaXNtbyBhZXJvcHVlcnRvLCBxdWUgc29uIGNhc2kgbGEgbWl0YWQsIGVzIG11eSBmYWN0aWJsZSBxdWUgc2VhbiB2dWVsb3MgZGUgZW50cmVuYW1pZW50by4KCkVuIGFlcnNDIHBvZGVtb3MgdmVyIGxvcyBhZXJvcHVlcnRvcyBxdWUgbm8gcmVnaXN0cmFuIGxvcyBldmVudG9zIHF1ZSBvY3VycmVuIGVuIGVsbG9zLiBBbCBtZW5vcyBzaSBjb25zaWRlcmFtb3Mgc29sbyBsb3MgdnVlbG9zIG5hY2lvbmFsZXMuIApgYGB7cn0KYWVyc0MgPSBOVUxMCmZvcih4IGluIGFlcnNCKXsKICBpZihzdW0oYWVyc0E9PXgpPT0wKQogIHsgCiAgICBpZihpcy5udWxsKGFlcnNDKSkgYWVyc0MgPSBjKHgpCiAgICBlbHNlIGFlcnNDID0gYyhhZXJzQyx4KQogIH0gIAp9CnByaW50KGFlcnNDKQpgYGAKCmBgYHtyfQojUG9yIGFob3JhIGVzdGEgcGFydGUgbm8gc2lydmUgcGVybyBlc3TDoSBidWVubyB0ZW5lcmxhCiMgQWdyZWdhbmRvIENpdWRhZGVzCgpkYXRvcyRjaXVkYWRfb3JpZ2VuICAgICA9IHJlcChOQSwgbGVuZ3RoKE4pKQpkYXRvcyRjaXVkYWRfZGVzdGlubyAgICA9IHJlcChOQSwgbGVuZ3RoKE4pKQpkYXRvcyRwcm92aW5jaWFfb3JpZ2VuICA9IHJlcChOQSwgbGVuZ3RoKE4pKQpkYXRvcyRwcm92aW5jaWFfZGVzdGlubyA9IHJlcChOQSwgbGVuZ3RoKE4pKQpkYXRvcyRsYXRfb3JpZ2VuICAgICAgICA9IHJlcChOQSwgbGVuZ3RoKE4pKSAKZGF0b3MkbG9uZ19vcmlnZW4gICAgICAgPSByZXAoTkEsIGxlbmd0aChOKSkgCmRhdG9zJGxhdF9kZXN0aW5vICAgICAgID0gcmVwKE5BLCBsZW5ndGgoTikpIApkYXRvcyRsb25nX2Rlc3Rpbm8gICAgICA9IHJlcChOQSwgbGVuZ3RoKE4pKSAKIyBkYXRvcyAlPiUgbXV0YXRlKGNpdWRhZF9vcmlnZW4gPSApICMgQWNhIHF1ZXJpYSBoYWNlciBleGFjdGFtZW50ZSBsbyBkZSBhcnJpYmEgcGVybyB1c2FuZG8gZHBseXIKCgoKIyBFbCBhbGdvcml0bW8gZGUgYWJham8gbmRhciBhbmRhLCB0YXJkYSB1biBtb250b24uIEhheSBxdWUgYWdyZWdhciBlbCByZXN0byBkZSBsYXMgdmFyaWFibGVzCgpmb3IoaSBpbiAxOmxlbmd0aChhZXJvcHVlcnRvcyRJQ0FPKSl7CiAgaW5kcyA9IGRhdG9zJE9yaWdlbi5PQUNJPT1hZXJvcHVlcnRvcyRJQ0FPW2ldCiAgZGF0b3NbaW5kcyxjKCdjaXVkYWRfb3JpZ2VuJywncHJvdmluY2lhX29yaWdlbicsJ2xhdF9vcmlnZW4nLCdsb25nX29yaWdlbicpXSA9IGFlcm9wdWVydG9zW2ksYygiQ2l0ecKgc2VydmVkIiwiUHJvdmluY2UiLCJsYXQiLCJsb25nIildCiAgCiAgaW5kcyA9IGRhdG9zJE9yaWdlbi5PQUNJPT1hZXJvcHVlcnRvcyRJQ0FPW2ldCiAgZGF0b3NbaW5kcyxjKCdjaXVkYWRfZGVzdGlubycsJ3Byb3ZpbmNpYV9kZXN0aW5vJywnbGF0X2Rlc3Rpbm8nLCdsb25nX2Rlc3Rpbm8nKV0gPSBhZXJvcHVlcnRvc1tpLGMoIkNpdHnCoHNlcnZlZCIsIlByb3ZpbmNlIiwibGF0IiwibG9uZyIpXQogIAogIAp9CmRhdG9zID0gZHJvcF9uYShkYXRvcykKZGF0b3MkZGlzdGFuY2lhID0gZGlzdEhhdmVyc2luZShkYXRvc1ssYygibG9uZ19vcmlnZW4iLCJsYXRfb3JpZ2VuIildLGRhdG9zWyxjKCJsb25nX2Rlc3Rpbm8iLCJsYXRfZGVzdGlubyIpXSkKYGBgCgoKCgo=